﻿namespace System.Dynamic
{
	using System.Collections.Generic;
	using System.Reflection;

	/// <summary>
	/// Represents a snapshot of an object.
	/// </summary>
	internal class ObjectSnapshot : DynamicObject
	{
		public ObjectSnapshot(object obj)
		{
			if (obj == null)
				throw new ArgumentNullException("obj");

			propertyValues = new Dictionary<string, object>();

			// create a snapshot of the current values of each property and field
			foreach (PropertyInfo pi in obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
			{
				try
				{
					propertyValues.Add(pi.Name, pi.GetValue(obj, null));
				}
				catch { }
			}

			foreach (FieldInfo fi in obj.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance))
			{
				try
				{
					propertyValues.Add(fi.Name, fi.GetValue(obj));
				}
				catch { }
			}
		}

		IDictionary<string, object> propertyValues;

		public override bool TryGetMember(GetMemberBinder binder, out object result)
		{
			return propertyValues.TryGetValue(binder.Name, out result);
		}

		public override IEnumerable<string> GetDynamicMemberNames()
		{
			return propertyValues.Keys;
		}
	}
}
